﻿using System;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Sripirom.ATS.Core.Messaging;
using Sripirom.ATS.Core.ServiceModel.Dispatcher;
using StructureMap;

namespace Sripirom.ATS.Core.ServiceModel.Description
{
    public class AtsEndpointBehavior : IEndpointBehavior
    {
        private readonly IDispatchMessageInspector _serviceTransactionLog;

        // ---- variable Service Pool Controller --------------
        private IInstanceProvider _instanceProvider;
        private Type _instanceProviderType;
        private Int32 _creationTimeout;
        private Int32 _maxPoolSize;
        private Int32 _minPoolSize;
        private Boolean _enabled;
        private Type _serviceType;
        // ----------------------------------------------------
        // type of impleent IDispatchMessageInspector
        private Type _messageInspector;

        // type of implement IErrorHandler
        private Type _errorHandler;


        public AtsEndpointBehavior(PoolingProviderConfigElement pooling,
                                            DispatchMessageInspectorConfigElement messageInspector,
                                            ErrorHandlerConfigElement errorHandler)
        {
            _serviceType = Type.GetType(pooling.ServiceType);
            _enabled = pooling.PoolEnabled;
            _maxPoolSize = pooling.MaxPoolSize;
            _minPoolSize = pooling.MinPoolSize;
            _creationTimeout = pooling.CreationTimeout;

            // innit instance pool
            _instanceProviderType = Type.GetType(pooling.Name);
            _enabled = true;

            _messageInspector = Type.GetType(messageInspector.Name);
            _errorHandler = Type.GetType(errorHandler.Name);


            _serviceTransactionLog = (IDispatchMessageInspector)System.Activator.CreateInstance(_messageInspector,
                ObjectFactory.Container.GetInstance(messageInspector.ConstructorAguments[0].InterfaceType),
                ObjectFactory.Container.GetInstance(messageInspector.ConstructorAguments[1].InterfaceType));

        }

        #region Pooling Properties
        /// <summary>
        /// Gets or sets the object creation time out
        /// </summary>
        public int CreationTimeout { get { return _creationTimeout; } set { _creationTimeout = value; } }

        /// <summary>
        /// Gets or sets the maximum number of objects
        /// can be created in the pool.
        /// </summary>
        public Int32 MaxPoolSize
        {
            get { return _maxPoolSize; }
            set
            {
                if (value < 0)
                {
                    throw new ArgumentException("ExNegetivePoolSize");
                }

                if (value < _minPoolSize)
                {
                    throw new ArgumentException("ExLowMaxPool");
                }
            }
        }

        /// <summary>
        /// Gets or sets the minium number of objects
        /// created in the pool.
        /// </summary>
        public Int32 MinPoolSize
        {
            get { return _minPoolSize; }
            set
            {
                if (value < 0)
                {
                    throw new ArgumentException("ExNegetivePoolSize");
                }

                if (_maxPoolSize > 0 && value > MaxPoolSize)
                {
                    throw new ArgumentException("ExHighMinPool");
                }

                MinPoolSize = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the object
        /// pooling is enabled or not.
        /// </summary>
        public Boolean Enabled { get { return _enabled; } set { _enabled = value; } }
        #endregion

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.ClientMessageInspectors.Add(new MessageInspector());
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
            //endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MessageInspector());
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(_serviceTransactionLog);


            endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add((IErrorHandler)Activator.CreateInstance(Type.GetType("Sripirom.ATS.Core.ExceptionHandler.MessageExceptionHandler, Sripirom.ATS.Core")));

            if (_enabled)
            {
                // Create an instance of the ObjectPoolInstanceProvider.
                _instanceProvider = (IInstanceProvider)System.Activator.CreateInstance(_instanceProviderType,
                    _serviceType,
                    _maxPoolSize, _minPoolSize, _creationTimeout);

                endpointDispatcher.DispatchRuntime.InstanceProvider = _instanceProvider;

            }

        }

        public void Validate(ServiceEndpoint endpoint)
        {

        }

    }
}




